#ifndef LISTASIMPLE_CPP
#define LISTASIMPLE_CPP

#include "ListaSimple.h"
#include "IteradorListaSimple.h"
#include "NodoListaSimple.h"
#include "Comparador.h"

template <class T>
ListaSimple<T>::ListaSimple()
{
	this->lista = NULL;
	this->tamanio = 0;
	this->ultimoElemento = NULL;
	
}


template <class T>
ListaSimple<T>::ListaSimple(Puntero<Comparador<T>> comparador)
{
	this->lista = NULL;
	this->tamanio = 0;
	this->ultimoElemento = NULL;
	this->comparador = comparador;
}

template <class T>
int ListaSimple<T>::Tamanio() const
{
	return this->tamanio;	
}


template <class T>
void ListaSimple<T>::InsertarAdelante(const T &x)
{
	if (!EsLlena())
	{
		Puntero<NodoListaSimple<T>> nuevo = new NodoListaSimple<T>();
		nuevo->Dato = x;
		nuevo->Sig = lista;

		if(EsVacia())
		{
			this->ultimoElemento = nuevo;
		}

		this->lista = nuevo;
		this->tamanio++;
	}
}

template <class T>
void ListaSimple<T>::InsertarAlFinal(const T &x)
{
	if (!EsLlena())
	{
		Puntero<NodoListaSimple<T>> nuevo = new NodoListaSimple<T>();
		nuevo->Dato = x;
		nuevo->Sig = NULL;

		if(EsVacia())
		{
			this->lista = nuevo;
		}else{
			this->ultimoElemento->Sig = nuevo;
		}

		this->ultimoElemento = nuevo;

		this->tamanio++;
	}
}

template <class T>
void ListaSimple<T>::InsertarOrdenado(const T &x)
{
	if (!EsLlena())
	{
		Puntero<NodoListaSimple<T>> anterior = NULL;
		Puntero<NodoListaSimple<T>> iter = lista;
		if(EsVacia()){
			this->InsertarAdelante(x);
		}else{
			while(iter!=NULL && (comparador->SonIguales(iter->Dato,x)||comparador->EsMenor(iter->Dato,x)))
			{
				anterior = iter;
				iter = iter->Sig;
			}
			if(anterior == NULL){
				this->InsertarAdelante(x);
			}else if(anterior == this->ultimoElemento)
			{
				InsertarAlFinal(x);
			}else{
				Puntero<NodoListaSimple<T>> nuevo = new NodoListaSimple<T>();
				nuevo->Dato = x;

				nuevo->Sig = anterior->Sig;
				anterior->Sig = nuevo;
			}
			this->tamanio++;
		}
	}
}

template <class T>
T ListaSimple<T>::ObtenerPrimerElemento() const
{
	return this->lista->Dato;
}

template <class T>
T ListaSimple<T>::ObtenerUltimoElemento() const
{
	return this->ultimoElemento->Dato;
}

template <class T>
bool ListaSimple<T>::EsVacia() const
{
	return this->tamanio == 0;
}

template <class T>
bool ListaSimple<T>::EsLlena() const
{
	return false;
}

template <class T>
bool ListaSimple<T>::Pertenece(const T &x) const
{
	Puntero<NodoListaSimple<T>> iter = lista;
	while(iter!=NULL && comparador->SonDistintos(iter->Dato,x))
	{
		iter = iter->Sig;
	}
	return iter!=NULL;
}

template <class T>
void ListaSimple<T>::EliminarPrimerElemento()
{
	if(!EsVacia()){
		if(this->lista == this->ultimoElemento){
			this->ultimoElemento = NULL;
		}
		this->lista = this->lista->Sig;
		this->tamanio--;
	}
}

template <class T>
void ListaSimple<T>::EliminarUltimoElemento()
{
	if(!EsVacia()){
		if(this->lista == this->ultimoElemento){
			this->ultimoElemento = NULL;
			this->lista = NULL;
		}else{
			Puntero<NodoListaSimple<T>> penultimo = this->lista;
			while(penultimo->Sig->Sig == NULL){
				penultimo = penultimo->Sig;
			}
			penultimo->Sig = NULL;
			this->ultimoElemento = penultimo;
		}
		this->tamanio--;
	}
}

template <class T>
void ListaSimple<T>::EliminarElemento(T &x)
{
	if(!this->EsVacia())
	{

		while(this->lista!=NULL && comparador->SonIguales(this->lista->Dato,x))
		{
			this->lista = this->lista->Sig;
			tamanio--;
		}

		if(this->lista!=NULL)
		{
			Puntero<NodoListaSimple<T>> anterior = this->lista;
			while(anterior!=NULL)
			{
				if(comparador->SonIguales(anterior->Sig->Dato,x))
				{
					if(anterior->Sig == this->ultimoElemento)
					{
						this->ultimoElemento = anterior;
					}
					anterior = anterior->Sig->Sig;
					tamanio--;
				}else
				{
					anterior = anterior->Sig;
				}
			}
		}else
		{
			this->ultimoElemento = NULL;
		}
	}
}


template <class T>
void ListaSimple<T>::Vaciar(){
	this->ultimoElemento = NULL;
	this->comparador = NULL;
	//this->lista = NULL;
	this->tamanio = 0;
}


template <class T>
Iterador<T> ListaSimple<T>::ObtenerIterador() const
{
	return new IteradorListaSimple<T>(lista);	
}

#endif
